package com.itaming.lycheeframework.support.utils;

import lombok.experimental.UtilityClass;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;

import java.util.*;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * Collection工具类
 *
 * @author A.Ming
 */
@UtilityClass
public class CollectionUtil {

    /**
     * 创建一个包含指定元素的 {@code ArrayList}
     *
     * @param elements 要包含的元素
     * @return 包含指定元素的 {@code ArrayList}，如果 {@code elements} 为 {@code null} 或空则返回空的 {@code ArrayList}
     */
    @NonNull
    @SafeVarargs
    public static <E> ArrayList<E> newArrayList(E... elements) {
        return newArrayList(NullSafeUtil.asList(elements));
    }

    /**
     * 创建一个包含指定元素的 {@code ArrayList}
     *
     * @param elements 要包含的元素
     * @return 包含指定元素的 {@code ArrayList}，如果 {@code elements} 为 {@code null} 或空则返回空的 {@code ArrayList}
     */
    @NonNull
    public static <E> ArrayList<E> newArrayList(Collection<? extends E> elements) {
        return isEmpty(elements) ? new ArrayList<>() : new ArrayList<>(elements);
    }

    /**
     * 创建一个包含指定元素的 {@code ArrayList}
     *
     * @param elements 要包含的元素
     * @return 包含指定元素的 {@code ArrayList}，如果 {@code elements} 为 {@code null} 或空则返回空的 {@code ArrayList}
     */
    @NonNull
    public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {
        return newArrayList(toIterator(elements));
    }

    /**
     * 创建一个包含指定元素的 {@code ArrayList}
     *
     * @param elements 要包含的元素
     * @return 包含指定元素的 {@code ArrayList}，如果 {@code elements} 为 {@code null} 或空则返回空的 {@code ArrayList}
     */
    @NonNull
    public static <E> ArrayList<E> newArrayList(Enumeration<? extends E> elements) {
        return newArrayList(toIterator(elements));
    }

    /**
     * 创建一个包含指定元素的 {@code ArrayList}
     *
     * @param elements 要包含的元素
     * @return 包含指定元素的 {@code ArrayList}，如果 {@code elements} 为 {@code null} 或空则返回空的 {@code ArrayList}
     */
    @NonNull
    public static <E> ArrayList<E> newArrayList(Iterator<? extends E> elements) {
        return newCollection(ArrayList::new, elements);
    }

    /**
     * 创建一个包含指定元素的 {@code HashSet}
     *
     * @param elements 要包含的元素
     * @return 包含指定元素的 {@code HashSet}，如果 {@code elements} 为 {@code null} 或空则返回空的 {@code HashSet}
     */
    @NonNull
    @SafeVarargs
    public static <E> HashSet<E> newHashSet(E... elements) {
        return newHashSet(NullSafeUtil.asList(elements));
    }

    /**
     * 创建一个包含指定元素的 {@code HashSet}
     *
     * @param elements 要包含的元素
     * @return 包含指定元素的 {@code HashSet}，如果 {@code elements} 为 {@code null} 或空则返回空的 {@code HashSet}
     */
    @NonNull
    public static <E> HashSet<E> newHashSet(Collection<? extends E> elements) {
        return isEmpty(elements) ? new HashSet<>() : new HashSet<>(elements);
    }

    /**
     * 创建一个包含指定元素的 {@code HashSet}
     *
     * @param elements 要包含的元素
     * @return 包含指定元素的 {@code HashSet}，如果 {@code elements} 为 {@code null} 或空则返回空的 {@code HashSet}
     */
    @NonNull
    public static <E> HashSet<E> newHashSet(Iterable<? extends E> elements) {
        return newHashSet(toIterator(elements));
    }

    /**
     * 创建一个包含指定元素的 {@code HashSet}
     *
     * @param elements 要包含的元素
     * @return 包含指定元素的 {@code HashSet}，如果 {@code elements} 为 {@code null} 或空则返回空的 {@code HashSet}
     */
    @NonNull
    public static <E> HashSet<E> newHashSet(Enumeration<? extends E> elements) {
        return newHashSet(toIterator(elements));
    }

    /**
     * 创建一个包含指定元素的 {@code HashSet}
     *
     * @param elements 要包含的元素
     * @return 包含指定元素的 {@code HashSet}，如果 {@code elements} 为 {@code null} 或空则返回空的 {@code HashSet}
     */
    @NonNull
    public static <E> HashSet<E> newHashSet(Iterator<? extends E> elements) {
        return newCollection(HashSet::new, elements);
    }

    /**
     * 获取集合，如果为 {@code null} 则返回空集合
     *
     * <p>
     * 返回的空 {@code List} 是 {@link Collections#emptyList()}，是不可修改的。
     *
     * @param collection 集合
     * @return 如果 {@code collection} 为 {@code null} 则返回空集合，否则返回原集合
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public static <T extends Collection<? super E>, E> T emptyIfNull(T collection) {
        return collection != null ? collection : (T) Collections.emptyList();
    }

    /**
     * 获取 {@code List}，如果为 {@code null} 则返回空 {@code List}
     *
     * <p>
     * 返回的空 {@code List} 是 {@link Collections#emptyList()}，是不可修改的。
     *
     * @param list 集合
     * @return 如果 {@code list} 为 {@code null} 则返回空 {@code List}，否则返回原 {@code List}
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public static <T extends List<? super E>, E> T emptyIfNull(T list) {
        return list != null ? list : (T) Collections.emptyList();
    }

    /**
     * 获取 {@code Set}，如果为 {@code null} 则返回空 {@code Set}
     *
     * <p>
     * 返回的空 {@code Set} 是 {@link Collections#emptySet()}，是不可修改的。
     *
     * @param set 集合
     * @return 如果 {@code set} 为 {@code null} 则返回空 {@code Set}，否则返回原 {@code Set}
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public static <T extends Set<? super E>, E> T emptyIfNull(T set) {
        return set != null ? set : (T) Collections.emptySet();
    }

    /**
     * 向集合中添加元素
     *
     * @param collection 集合
     * @param elements   要添加的元素
     * @return 添加元素后的原集合，如果 {@code collection} 为 {@code null} 则不执行添加操作，直接返回原集合
     */
    @SafeVarargs
    public static <T extends Collection<? super E>, E> T addAll(T collection, E... elements) {
        return addAll(collection, NullSafeUtil.asList(elements));
    }

    /**
     * 向集合中添加元素
     *
     * @param collection 集合
     * @param elements   要添加的元素
     * @return 添加元素后的原集合，如果 {@code collection} 为 {@code null} 则不执行添加操作，直接返回原集合
     */
    public static <T extends Collection<? super E>, E> T addAll(T collection, Collection<E> elements) {
        if (collection != null && isNotEmpty(elements)) {
            collection.addAll(elements);
        }
        return collection;
    }

    /**
     * 向集合中添加元素
     *
     * @param collection 集合
     * @param elements   要添加的元素
     * @return 添加元素后的原集合，如果 {@code collection} 为 {@code null} 则不执行添加操作，直接返回原集合
     */
    public static <T extends Collection<? super E>, E> T addAll(T collection, Iterable<E> elements) {
        return addAll(collection, toIterator(elements));
    }

    /**
     * 向集合中添加元素
     *
     * @param collection 集合
     * @param elements   要添加的元素
     * @return 添加元素后的原集合，如果 {@code collection} 为 {@code null} 则不执行添加操作，直接返回原集合
     */
    public static <T extends Collection<? super E>, E> T addAll(T collection, Enumeration<E> elements) {
        return addAll(collection, toIterator(elements));
    }

    /**
     * 向集合中添加元素
     *
     * @param collection 集合
     * @param elements   要添加的元素
     * @return 添加元素后的原集合，如果 {@code collection} 为 {@code null} 则不执行添加操作，直接返回原集合
     */
    public static <T extends Collection<? super E>, E> T addAll(T collection, Iterator<E> elements) {
        if (collection != null && elements != null) {
            while (elements.hasNext()) {
                collection.add(elements.next());
            }
        }
        return collection;
    }

    /**
     * 判断任意元素是否匹配
     *
     * @param collection 集合
     * @param predicate  判断函数
     * @return boolean
     */
    public static <E> boolean anyMatch(Collection<E> collection, Predicate<E> predicate) {
        return anyMatch(toIterator(collection), predicate);
    }

    /**
     * 判断任意元素是否匹配
     *
     * @param iterable  可迭代对象
     * @param predicate 判断函数
     * @return boolean
     */
    public static <E> boolean anyMatch(Iterable<E> iterable, Predicate<E> predicate) {
        return anyMatch(toIterator(iterable), predicate);
    }

    /**
     * 判断任意元素是否匹配
     *
     * @param enumeration 枚举器
     * @param predicate   判断函数
     * @return boolean
     */
    public static <E> boolean anyMatch(Enumeration<E> enumeration, Predicate<E> predicate) {
        return anyMatch(toIterator(enumeration), predicate);
    }

    /**
     * 判断任意元素是否匹配
     *
     * @param iterator  迭代器
     * @param predicate 判断函数
     * @return boolean
     */
    public static <E> boolean anyMatch(Iterator<E> iterator, Predicate<E> predicate) {
        checkPredicate(predicate);

        if (isEmpty(iterator)) {
            return false;
        }

        while (iterator.hasNext()) {
            if (predicate.test(iterator.next())) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断所有元素是否匹配
     *
     * @param collection 集合
     * @param predicate  判断函数
     * @return boolean
     */
    public static <E> boolean allMatch(Collection<E> collection, Predicate<E> predicate) {
        return allMatch(toIterator(collection), predicate);
    }

    /**
     * 判断所有元素是否匹配
     *
     * @param iterable  可迭代对象
     * @param predicate 判断函数
     * @return boolean
     */
    public static <E> boolean allMatch(Iterable<E> iterable, Predicate<E> predicate) {
        return allMatch(toIterator(iterable), predicate);
    }

    /**
     * 判断所有元素是否匹配
     *
     * @param enumeration 枚举器
     * @param predicate   判断函数
     * @return boolean
     */
    public static <E> boolean allMatch(Enumeration<E> enumeration, Predicate<E> predicate) {
        return allMatch(toIterator(enumeration), predicate);
    }

    /**
     * 判断所有元素是否匹配
     *
     * @param iterator  迭代器
     * @param predicate 判断函数
     * @return boolean
     */
    public static <E> boolean allMatch(Iterator<E> iterator, Predicate<E> predicate) {
        checkPredicate(predicate);

        if (isEmpty(iterator)) {
            return false;
        }

        while (iterator.hasNext()) {
            if (!predicate.test(iterator.next())) {
                return false;
            }
        }

        return true;
    }

    /**
     * 判断是否包含指定的元素
     *
     * @param collection 集合
     * @param element    要查找的元素
     * @return boolean
     */
    public static <E> boolean contains(Collection<E> collection, E element) {
        if (isEmpty(collection)) {
            return false;
        }

        // 集合转换为 Set，优化时间复杂度
        Set<E> collectionSet = toSetIfNeeded(collection);

        return collectionSet.contains(element);
    }

    /**
     * 判断是否包含指定的元素
     *
     * @param iterable 可迭代对象
     * @param element  要查找的元素
     * @return boolean
     */
    public static <E> boolean contains(Iterable<E> iterable, E element) {
        return contains(toIterator(iterable), element);
    }

    /**
     * 判断是否包含指定的元素
     *
     * @param enumeration 枚举器
     * @param element     要查找的元素
     * @return boolean
     */
    public static <E> boolean contains(Enumeration<E> enumeration, E element) {
        return contains(toIterator(enumeration), element);
    }

    /**
     * 判断集合是否包含指定的元素
     *
     * @param iterator 迭代器
     * @param element  要查找的元素
     * @return boolean
     */
    public static <E> boolean contains(Iterator<E> iterator, E element) {
        if (isEmpty(iterator)) {
            return false;
        }

        while (iterator.hasNext()) {
            if (Objects.equals(iterator.next(), element)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断是否包含指定元素的任意一个
     *
     * @param collection 集合
     * @param elements   要查找的元素
     * @return boolean
     */
    @SafeVarargs
    public static <E> boolean containsAny(Collection<E> collection, E... elements) {
        return containsAny(collection, NullSafeUtil.asList(elements));
    }

    /**
     * 判断是否包含指定元素的任意一个
     *
     * @param collection 集合
     * @param elements   要查找的元素
     * @return boolean
     */
    public static <E> boolean containsAny(Collection<E> collection, Collection<E> elements) {
        if (isEmpty(collection) || isEmpty(elements)) {
            return false;
        }

        // 将较小的集合转为 Set，优化时间复杂度
        Set<E> sourceSet;
        Collection<E> targetCollection;
        if (collection.size() > elements.size()) {
            sourceSet = toSetIfNeeded(elements);
            targetCollection = collection;
        } else {
            sourceSet = toSetIfNeeded(collection);
            targetCollection = elements;
        }

        for (E e : targetCollection) {
            if (sourceSet.contains(e)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断是否包含指定元素的任意一个
     *
     * @param collection 集合
     * @param elements   要查找的元素
     * @return boolean
     */
    public static <E> boolean containsAny(Collection<E> collection, Iterable<E> elements) {
        return containsAny(collection, toIterator(elements));
    }

    /**
     * 判断是否包含指定元素的任意一个
     *
     * @param collection 集合
     * @param elements   要查找的元素
     * @return boolean
     */
    public static <E> boolean containsAny(Collection<E> collection, Enumeration<E> elements) {
        return containsAny(collection, toIterator(elements));
    }

    /**
     * 判断是否包含指定元素的任意一个
     *
     * @param collection 集合
     * @param elements   要查找的元素
     * @return boolean
     */
    public static <E> boolean containsAny(Collection<E> collection, Iterator<E> elements) {
        if (isEmpty(collection) || isEmpty(elements)) {
            return false;
        }

        // 集合转为 Set，优化时间复杂度
        Set<E> collectionSet = toSetIfNeeded(collection);
        while (elements.hasNext()) {
            if (collectionSet.contains(elements.next())) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断是否包含指定的所有元素
     *
     * @param collection 集合
     * @param elements   要查找的元素
     * @return boolean
     */
    @SafeVarargs
    public static <E> boolean containsAll(Collection<E> collection, E... elements) {
        return containsAll(collection, NullSafeUtil.asList(elements));
    }

    /**
     * 判断是否包含指定的所有元素
     *
     * @param collection 集合
     * @param elements   要查找的元素
     * @return boolean
     */
    public static <E> boolean containsAll(Collection<E> collection, Collection<E> elements) {
        if (isEmpty(collection) || isEmpty(elements)) {
            return false;
        }

        // 集合转为 Set，优化时间复杂度
        Set<E> collectionSet = toSetIfNeeded(collection);
        Set<E> elementSet = toSetIfNeeded(elements);

        // 要查找的元素数量大于集合数量，必定不可能全部包含
        if (elementSet.size() > collectionSet.size()) {
            return false;
        }

        return collectionSet.containsAll(elementSet);
    }

    /**
     * 判断是否包含指定的所有元素
     *
     * @param collection 集合
     * @param iterable   要查找的元素
     * @return boolean
     */
    public static <E> boolean containsAll(Collection<E> collection, Iterable<E> iterable) {
        return containsAll(collection, toIterator(iterable));
    }

    /**
     * 判断是否包含指定的所有元素
     *
     * @param collection  集合
     * @param enumeration 要查找的元素
     * @return boolean
     */
    public static <E> boolean containsAll(Collection<E> collection, Enumeration<E> enumeration) {
        return containsAll(collection, toIterator(enumeration));
    }

    /**
     * 判断是否包含指定的所有元素
     *
     * @param collection 集合
     * @param elements   要查找的元素
     * @return boolean
     */
    public static <E> boolean containsAll(Collection<E> collection, Iterator<E> elements) {
        if (isEmpty(collection) || isEmpty(elements)) {
            return false;
        }

        // 集合转为 Set，优化时间复杂度
        Set<E> collectionSet = toSetIfNeeded(collection);
        while (elements.hasNext()) {
            if (!collectionSet.contains(elements.next())) {
                return false;
            }
        }

        return true;
    }

    /**
     * 查找第一个符合条件的元素
     *
     * @param iterable  可迭代对象
     * @param predicate 判断函数
     * @return 第一个符合条件的元素，未找到返回 {@code null}
     */
    public static <E> E findFirst(Iterable<E> iterable, Predicate<E> predicate) {
        return findFirst(toIterator(iterable), predicate);
    }

    /**
     * 查找第一个符合条件的元素
     *
     * @param enumeration 枚举器
     * @param predicate   判断函数
     * @return 第一个符合条件的元素，未找到返回 {@code null}
     */
    public static <E> E findFirst(Enumeration<E> enumeration, Predicate<E> predicate) {
        return findFirst(toIterator(enumeration), predicate);
    }

    /**
     * 查找第一个符合条件的元素
     *
     * @param iterator  迭代器
     * @param predicate 判断函数
     * @return 第一个符合条件的元素，未找到返回 {@code null}
     */
    public static <E> E findFirst(Iterator<E> iterator, Predicate<E> predicate) {
        if (isEmpty(iterator)) {
            return null;
        }

        while (iterator.hasNext()) {
            E e = iterator.next();
            if (predicate.test(e)) {
                return e;
            }
        }

        return null;
    }

    /**
     * 查找最后一个符合条件的元素
     *
     * @param iterable  可迭代对象
     * @param predicate 判断函数
     * @return 最后一个符合条件的元素，未找到返回 {@code null}
     */
    public static <E> E findLast(Iterable<E> iterable, Predicate<E> predicate) {
        return findLast(toIterator(iterable), predicate);
    }

    /**
     * 查找最后一个符合条件的元素
     *
     * @param enumeration 枚举器
     * @param predicate   判断函数
     * @return 最后一个符合条件的元素，未找到返回 {@code null}
     */
    public static <E> E findLast(Enumeration<E> enumeration, Predicate<E> predicate) {
        return findLast(toIterator(enumeration), predicate);
    }

    /**
     * 查找最后一个符合条件的元素
     *
     * @param iterator  迭代器
     * @param predicate 判断函数
     * @return 最后一个符合条件的元素，未找到返回 {@code null}
     */
    public static <E> E findLast(Iterator<E> iterator, Predicate<E> predicate) {
        if (isEmpty(iterator)) {
            return null;
        }

        E result = null;
        while (iterator.hasNext()) {
            E e = iterator.next();
            if (predicate.test(e)) {
                result = e;
            }
        }

        return result;
    }

    /**
     * 获取第一个元素
     *
     * <p>
     * 如果是 {@code List} 则直接返回第一个元素，否则返回迭代器的第一个元素
     *
     * @param collection 集合
     * @return 集合的第一个元素，{@code collection} 为 {@code null} 或空时返回 {@code null}
     */
    public static <E> E getFirst(Collection<E> collection) {
        if (isEmpty(collection)) {
            return null;
        }

        if (collection instanceof List<E> list) {
            return list.get(0);
        }

        return getFirst(collection.iterator());
    }

    /**
     * 获取第一个元素
     *
     * @param iterable 可迭代对象
     * @return 迭代器的第一个元素，{@code iterable} 为 {@code null} 或空时返回 {@code null}
     */
    public static <E> E getFirst(Iterable<E> iterable) {
        return getFirst(toIterator(iterable));
    }

    /**
     * 获取第一个元素
     *
     * @param enumeration 枚举器
     * @return 迭代器的第一个元素，{@code enumeration} 为 {@code null} 或空时返回 {@code null}
     */
    public static <E> E getFirst(Enumeration<E> enumeration) {
        return getFirst(toIterator(enumeration));
    }

    /**
     * 获取第一个元素
     *
     * @param iterator 迭代器
     * @return 迭代器的第一个元素，{@code iterator} 为 {@code null} 或空时返回 {@code null}
     */
    public static <E> E getFirst(Iterator<E> iterator) {
        return isEmpty(iterator) ? null : iterator.next();
    }

    /**
     * 获取最后一个元素
     *
     * <p>
     * 如果是 {@code List} 则直接返回最后一个元素，否则返回迭代器的最后一个元素
     *
     * @param collection 集合
     * @return 集合的最后一个元素，{@code collection} 为 {@code null} 或空时返回 {@code null}
     */
    public static <E> E getLast(Collection<E> collection) {
        if (isEmpty(collection)) {
            return null;
        }

        if (collection instanceof List<E> list) {
            return list.get(list.size() - 1);
        }

        return getLast(collection.iterator());
    }

    /**
     * 获取最后一个元素
     *
     * @param iterable 可迭代对象
     * @return 迭代器的最后一个元素，{@code iterable} 为 {@code null} 或空时返回 {@code null}
     */
    public static <E> E getLast(Iterable<E> iterable) {
        return getLast(toIterator(iterable));
    }

    /**
     * 获取最后一个元素
     *
     * @param enumeration 枚举器
     * @return 迭代器的最后一个元素，{@code enumeration} 为 {@code null} 或空时返回 {@code null}
     */
    public static <E> E getLast(Enumeration<E> enumeration) {
        return getLast(toIterator(enumeration));
    }

    /**
     * 获取最后一个元素
     *
     * @param iterator 迭代器
     * @return 迭代器的最后一个元素，{@code iterator} 为 {@code null} 或空时返回 {@code null}
     */
    public static <E> E getLast(Iterator<E> iterator) {
        E last = null;

        if (iterator != null) {
            while (iterator.hasNext()) {
                last = iterator.next();
            }
        }

        return last;
    }

    /**
     * 获取指定位置的元素
     *
     * <p>
     * 如果是 {@code List} 则直接返回指定位置的元素，否则返回迭代器的指定位置的元素
     *
     * @param collection 集合
     * @param index      索引
     * @return 集合指定位置的元素，未找到或索引越界返回 {@code null}
     */
    public static <E> E get(Collection<E> collection, int index) {
        if (collection == null) {
            return null;
        }

        if (!isValidIndex(collection, index)) {
            return null;
        }

        if (collection instanceof List<E> list) {
            return list.get(index);
        }

        return get(collection.iterator(), index);
    }

    /**
     * 获取指定位置的元素
     *
     * @param iterable 可迭代对象
     * @param index    索引
     * @return 迭代器指定位置的元素，未找到或索引越界返回 {@code null}
     */
    public static <E> E get(Iterable<E> iterable, int index) {
        return get(toIterator(iterable), index);
    }

    /**
     * 获取指定位置的元素
     *
     * @param enumeration 枚举器
     * @param index       索引
     * @return 迭代器指定位置的元素，未找到或索引越界返回 {@code null}
     */
    public static <E> E get(Enumeration<E> enumeration, int index) {
        return get(toIterator(enumeration), index);
    }

    /**
     * 获取指定位置的元素
     *
     * @param iterator 迭代器
     * @param index    索引
     * @return 迭代器指定位置的元素，未找到或索引越界返回 {@code null}
     */
    public static <E> E get(Iterator<E> iterator, int index) {
        if (iterator == null || index < 0) {
            return null;
        }

        while (iterator.hasNext()) {
            if (index == 0) {
                return iterator.next();
            }
            --index;
            iterator.next();
        }

        return null;
    }

    /**
     * 统计指定的元素个数
     *
     * @param iterable 可迭代对象
     * @param element  要统计的元素
     * @return 指定的元素个数
     */
    public static <E> int count(Iterable<E> iterable, E element) {
        return count(toIterator(iterable), element);
    }

    /**
     * 统计指定的元素个数
     *
     * @param enumeration 枚举器
     * @param element     要统计的元素
     * @return 指定的元素个数
     */
    public static <E> int count(Enumeration<E> enumeration, E element) {
        return count(toIterator(enumeration), element);
    }

    /**
     * 统计指定的元素个数
     *
     * @param iterator 迭代器
     * @param element  要统计的元素
     * @return 指定的元素个数
     */
    public static <E> int count(Iterator<E> iterator, E element) {
        int count = 0;
        if (iterator != null) {
            while (iterator.hasNext()) {
                if (Objects.equals(iterator.next(), element)) {
                    count++;
                }
            }
        }

        return count;
    }

    /**
     * 统计符合条件的元素个数
     *
     * @param iterable  可迭代对象
     * @param predicate 判断函数
     * @return 符合条件的元素个数
     */
    public static <E> int count(Iterable<E> iterable, Predicate<E> predicate) {
        return count(toIterator(iterable), predicate);
    }

    /**
     * 统计符合条件的元素个数
     *
     * @param enumeration 枚举器
     * @param predicate   判断函数
     * @return 符合条件的元素个数
     */
    public static <E> int count(Enumeration<E> enumeration, Predicate<E> predicate) {
        return count(toIterator(enumeration), predicate);
    }

    /**
     * 统计符合条件的元素个数
     *
     * @param iterator  迭代器
     * @param predicate 判断函数
     * @return 符合条件的元素个数
     */
    public static <E> int count(Iterator<E> iterator, Predicate<E> predicate) {
        checkPredicate(predicate);

        int count = 0;
        if (iterator != null) {
            while (iterator.hasNext()) {
                if (predicate.test(iterator.next())) {
                    count++;
                }
            }
        }

        return count;
    }

    /**
     * 判断是否为空
     *
     * @param collection 集合
     * @return boolean
     */
    public static boolean isEmpty(Collection<?> collection) {
        return collection == null || collection.isEmpty();
    }

    /**
     * 判断是否为空
     *
     * @param iterator 迭代器
     * @return boolean
     */
    public static boolean isEmpty(Iterator<?> iterator) {
        return iterator == null || !iterator.hasNext();
    }

    /**
     * 判断是否为空
     *
     * @param iterable 可迭代对象
     * @return boolean
     */
    public static boolean isEmpty(Iterable<?> iterable) {
        return isEmpty(toIterator(iterable));
    }

    /**
     * 判断是否为空
     *
     * @param enumeration 枚举器
     * @return boolean
     */
    public static boolean isEmpty(Enumeration<?> enumeration) {
        return enumeration == null || !enumeration.hasMoreElements();
    }

    /**
     * 判断是否为空
     *
     * @param map 映射
     * @return boolean
     */
    public static boolean isEmpty(Map<?, ?> map) {
        return map == null || map.isEmpty();
    }

    /**
     * 判断是否不为空
     *
     * @param collection 集合
     * @return boolean
     */
    public static boolean isNotEmpty(Collection<?> collection) {
        return !isEmpty(collection);
    }

    /**
     * 判断是否不为空
     *
     * @param iterator 迭代器
     * @return boolean
     */
    public static boolean isNotEmpty(Iterator<?> iterator) {
        return !isEmpty(iterator);
    }

    /**
     * 判断是否不为空
     *
     * @param iterable 可迭代对象
     * @return boolean
     */
    public static boolean isNotEmpty(Iterable<?> iterable) {
        return !isEmpty(iterable);
    }

    /**
     * 判断是否不为空
     *
     * @param enumeration 枚举器
     * @return boolean
     */
    public static boolean isNotEmpty(Enumeration<?> enumeration) {
        return !isEmpty(enumeration);
    }

    /**
     * 判断是否任意元素为 {@code null}
     *
     * @param iterable 可迭代对象
     * @return boolean
     */
    public static boolean isAnyNull(Iterable<?> iterable) {
        return isAnyNull(toIterator(iterable));
    }

    /**
     * 判断是否任意元素为 {@code null}
     *
     * @param enumeration 枚举器
     * @return boolean
     */
    public static boolean isAnyNull(Enumeration<?> enumeration) {
        return isAnyNull(toIterator(enumeration));
    }

    /**
     * 判断是否任意元素为 {@code null}
     *
     * @param iterator 迭代器
     * @return boolean
     */
    public static boolean isAnyNull(Iterator<?> iterator) {
        if (iterator == null) {
            return false;
        }

        while (iterator.hasNext()) {
            if (iterator.next() == null) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断是否任意元素不为 {@code null}
     *
     * @param iterable 可迭代对象
     * @return boolean
     */
    public static boolean isAnyNotNull(Iterable<?> iterable) {
        return isAnyNotNull(toIterator(iterable));
    }

    /**
     * 判断是否任意元素不为 {@code null}
     *
     * @param enumeration 枚举器
     * @return boolean
     */
    public static boolean isAnyNotNull(Enumeration<?> enumeration) {
        return isAnyNotNull(toIterator(enumeration));
    }

    /**
     * 判断是否任意元素不为 {@code null}
     *
     * @param iterator 迭代器
     * @return boolean
     */
    public static boolean isAnyNotNull(Iterator<?> iterator) {
        if (iterator == null) {
            return false;
        }

        while (iterator.hasNext()) {
            if (iterator.next() != null) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断是否所有元素均为 {@code null}
     *
     * <p>
     * 空集合将被视为 {@code true}，这是基于逻辑学中的 Vacuous Truth（空真）原则，
     * 当集合中没有元素时，所有元素满足某一条件的命题在逻辑上被认为为真。
     * 参考 <a href="https://en.wikipedia.org/wiki/Vacuous_truth">Vacuous Truth</a>
     * 中的 {@code In computer programming} 章节。
     * <p>
     * 此行为与主流工具库（如 Apache Commons 等）保持一致
     *
     * @param iterable 可迭代对象
     * @return boolean
     */
    public static boolean isAllNull(Iterable<?> iterable) {
        return isAllNull(toIterator(iterable));
    }

    /**
     * 判断是否所有元素均为 {@code null}
     *
     * <p>
     * 空集合将被视为 {@code true}，这是基于逻辑学中的 Vacuous Truth（空真）原则，
     * 当集合中没有元素时，所有元素满足某一条件的命题在逻辑上被认为为真。
     * 参考 <a href="https://en.wikipedia.org/wiki/Vacuous_truth">Vacuous Truth</a>
     * 中的 {@code In computer programming} 章节。
     * <p>
     * 此行为与主流工具库（如 Apache Commons 等）保持一致
     *
     * @param enumeration 枚举器
     * @return boolean
     */
    public static boolean isAllNull(Enumeration<?> enumeration) {
        return isAllNull(toIterator(enumeration));
    }

    /**
     * 判断是否所有元素均为 {@code null}
     *
     * <p>
     * 空集合将被视为 {@code true}，这是基于逻辑学中的 Vacuous Truth（空真）原则，
     * 当集合中没有元素时，所有元素满足某一条件的命题在逻辑上被认为为真。
     * 参考 <a href="https://en.wikipedia.org/wiki/Vacuous_truth">Vacuous Truth</a>
     * 中的 {@code In computer programming} 章节。
     * <p>
     * 此行为与主流工具库（如 Apache Commons 等）保持一致
     *
     * @param iterator 迭代器
     * @return boolean
     */
    public static boolean isAllNull(Iterator<?> iterator) {
        return !isAnyNotNull(iterator);
    }

    /**
     * 判断是否所有元素均不为 {@code null}
     *
     * <p>
     * 空集合将被视为 {@code true}，这是基于逻辑学中的 Vacuous Truth（空真）原则，
     * 当集合中没有元素时，所有元素满足某一条件的命题在逻辑上被认为为真。
     * 参考 <a href="https://en.wikipedia.org/wiki/Vacuous_truth">Vacuous Truth</a>
     * 中的 {@code In computer programming} 章节。
     * <p>
     * 此行为与主流工具库（如 Apache Commons 等）保持一致
     *
     * @param iterable 可迭代对象
     * @return boolean
     */
    public static boolean isAllNotNull(Iterable<?> iterable) {
        return isAllNotNull(toIterator(iterable));
    }

    /**
     * 判断是否所有元素均不为 {@code null}
     *
     * <p>
     * 空集合将被视为 {@code true}，这是基于逻辑学中的 Vacuous Truth（空真）原则，
     * 当集合中没有元素时，所有元素满足某一条件的命题在逻辑上被认为为真。
     * 参考 <a href="https://en.wikipedia.org/wiki/Vacuous_truth">Vacuous Truth</a>
     * 中的 {@code In computer programming} 章节。
     * <p>
     * 此行为与主流工具库（如 Apache Commons 等）保持一致
     *
     * @param enumeration 枚举器
     * @return boolean
     */
    public static boolean isAllNotNull(Enumeration<?> enumeration) {
        return isAllNotNull(toIterator(enumeration));
    }

    /**
     * 判断是否所有元素均不为 {@code null}
     *
     * <p>
     * 空集合将被视为 {@code true}，这是基于逻辑学中的 Vacuous Truth（空真）原则，
     * 当集合中没有元素时，所有元素满足某一条件的命题在逻辑上被认为为真。
     * 参考 <a href="https://en.wikipedia.org/wiki/Vacuous_truth">Vacuous Truth</a>
     * 中的 {@code In computer programming} 章节。
     * <p>
     * 此行为与主流工具库（如 Apache Commons 等）保持一致
     *
     * @param iterator 迭代器
     * @return boolean
     */
    public static boolean isAllNotNull(Iterator<?> iterator) {
        return !isAnyNull(iterator);
    }

    /**
     * 判断是否为有效索引
     *
     * @param collection 集合
     * @param index      索引
     * @return boolean
     */
    public static boolean isValidIndex(Collection<?> collection, int index) {
        return index >= 0 && index < collection.size();
    }

    /**
     * 获取迭代器
     *
     * @param iterable 可迭代对象
     * @return 迭代器，传入 {@code null} 时返回空迭代器
     */
    public static <E> Iterator<E> toIterator(Iterable<E> iterable) {
        return iterable != null ? iterable.iterator() : Collections.emptyIterator();
    }

    /**
     * 获取迭代器
     *
     * @param enumeration 枚举器
     * @return 迭代器，传入 {@code null} 时返回空迭代器
     */
    public static <E> Iterator<E> toIterator(Enumeration<E> enumeration) {
        return enumeration != null ? enumeration.asIterator() : Collections.emptyIterator();
    }

    /**
     * 获取集合长度
     *
     * @param collection 集合
     * @return 集合长度
     */
    public static int size(Collection<?> collection) {
        return isEmpty(collection) ? 0 : collection.size();
    }

    /**
     * 交换列表元素
     *
     * @param list   列表
     * @param index1 索引1
     * @param index2 索引2
     * @return 交换元素后的列表，如果 {@code list} 为 {@code null} 或空，则不执行交换直接返回原列表
     * @throws IndexOutOfBoundsException 索引越界时抛出
     */
    public static <T extends List<?>> T swap(T list, int index1, int index2) {
        if (isEmpty(list) || index1 == index2) {
            return list;
        }

        // 校验索引
        Objects.checkIndex(index1, list.size());
        Objects.checkIndex(index2, list.size());

        // 交换元素
        Collections.swap(list, index1, index2);

        return list;
    }

    /**
     * 反转列表
     *
     * @param list 列表
     * @return 反转后的列表，如果 {@code list} 为 {@code null} 或空，则不执行反转直接返回原列表
     */
    public <T extends List<?>> T reverse(T list) {
        if (isEmpty(list)) {
            return list;
        }

        // 反转
        Collections.reverse(list);

        return list;
    }

    /**
     * 打乱列表
     *
     * @param list 列表
     * @return 打乱后的列表，如果 {@code list} 为 {@code null} 或空，则不执行打乱直接返回原列表
     */
    public static <T extends List<?>> T shuffle(T list) {
        return shuffle(list, null);
    }

    /**
     * 打乱列表
     *
     * @param list   列表
     * @param random 随机数生成器
     * @return 打乱后的列表，如果 {@code list} 为 {@code null} 或空，则不执行打乱直接返回原列表
     */
    public static <T extends List<?>> T shuffle(T list, Random random) {
        if (isEmpty(list)) {
            return list;
        }

        // 打乱
        if (random == null) {
            Collections.shuffle(list);
        } else {
            Collections.shuffle(list, random);
        }

        return list;
    }

    /**
     * 排序列表
     *
     * @param list       列表
     * @param comparator 比较器
     * @return 排序后的列表，如果 {@code list} 为 {@code null} 或空，则不执行排序直接返回原列表
     */
    public static <E> List<E> sort(List<E> list, Comparator<E> comparator) {
        if (isEmpty(list)) {
            return list;
        }

        // 排序
        list.sort(comparator);

        return list;
    }

    /**
     * 截取列表中从 {@code startIndex} 到 {@code endIndex} 的元素
     *
     * @param list       列表
     * @param startIndex 开始位置(包含)
     * @param endIndex   结束位置(不包含，负数表示列表末尾)
     * @return 包含所有被截取元素的新 {@code ArrayList}，如果 {@code list} 为 {@code null} 或空，则返回空 {@code ArrayList}
     */
    public static <E> List<E> subList(List<E> list, int startIndex, int endIndex) {
        if (isEmpty(list)) {
            return new ArrayList<>();
        }

        int size = list.size();
        int start = Math.min(Math.max(startIndex, 0), size);
        int end = (endIndex < 0 || endIndex > size) ? size : endIndex;

        int newLength = end - start;
        if (newLength <= 0) {
            return new ArrayList<>();
        }

        ArrayList<E> subList = new ArrayList<>(newLength - 1);
        subList.addAll(list.subList(start, end));

        return subList;
    }

    /**
     * 获取两个集合的交集
     *
     * <p>
     * 返回包含两个集合中都存在的元素的新 {@code Set}，任一集合为 {@code null} 或空时返回空 {@code Set}
     *
     * @param c1 集合1
     * @param c2 集合2
     * @return 包含交集结果的新 {@code Set}
     */
    public static <T> Set<T> intersection(Collection<T> c1, Collection<T> c2) {
        if (isEmpty(c1) || isEmpty(c2)) {
            return new HashSet<>();
        }

        Set<T> result = new HashSet<>(c1);
        result.retainAll(c2);

        return result;
    }

    /**
     * 获取多个集合的交集
     *
     * <p>
     * 返回包含所有集合中都存在的元素的新 {@code Set}，任一集合为 {@code null} 或空时返回空 {@code Set}
     *
     * @param c1   集合1
     * @param c2   集合2
     * @param more 更多集合
     * @return 包含交集结果的新 {@code Set}
     */
    @SafeVarargs
    public static <T> Set<T> intersection(Collection<T> c1, Collection<T> c2, Collection<T>... more) {
        Set<T> result = intersection(c1, c2);
        if (result.isEmpty()) {
            return result;
        }

        for (Collection<T> c : more) {
            result = intersection(result, c);
            if (result.isEmpty()) {
                break;
            }
        }

        return result;
    }

    /**
     * 获取两个集合的差集
     *
     * <p>
     * 以 {@code c1} 作为基准集合，返回一个新的 {@code Set}，
     * 包含所有在 {@code c1} 中存在但在 {@code c2} 中不存在的元素
     * <ul>
     *     <li>如果 {@code c1} 为 {@code null} 或空，返回空 {@code Set}</li>
     *     <li>如果 {@code c2} 为 {@code null} 或空，返回包含 {@code c1} 中所有元素的新 {@code Set}</li>
     * </ul>
     *
     * @param c1 集合1
     * @param c2 集合2
     * @return 包含差集结果的新 {@code Set}
     */
    public static <T> Set<T> difference(Collection<T> c1, Collection<T> c2) {
        if (isEmpty(c1)) {
            return new HashSet<>();
        }

        Set<T> result = new HashSet<>(c1);
        if (!isEmpty(c2)) {
            result.removeAll(c2);
        }

        return result;
    }

    /**
     * 获取多个集合的差集
     *
     * <p>
     * 以 {@code c1} 为初始基准集合，依次与 {@code c2} 及 {@code more} 中的每一个集合进行差集运算，
     * 最终返回包含所有仅出现在基准集合中、且未出现在后续任一集合中的元素的新 {@code Set}。
     * <p>
     * 多个集合的运算规则：
     * <ul>
     *     <li>以 {@code c1} 作为基准集合</li>
     *     <li>每个后续集合({@code c2} 与 {@code more})按顺序参与运算，并将结果作为新的基准集合</li>
     *     <li>如果当前基准集合为空或为 {@code null}，立即返回空 {@code Set}</li>
     *     <li>如果某个后续集合为 {@code null} 或为空，则忽略该集合</li>
     * </ul>
     *
     * @param c1   集合1
     * @param c2   集合2
     * @param more 更多集合
     * @return 包含差集结果的新 {@code Set}
     */
    @SafeVarargs
    public static <T> Set<T> difference(Collection<T> c1, Collection<T> c2, Collection<T>... more) {
        Set<T> result = difference(c1, c2);
        if (result.isEmpty()) {
            return result;
        }

        for (Collection<T> c : more) {
            result = difference(result, c);
            if (result.isEmpty()) {
                break;
            }
        }

        return result;
    }

    /**
     * 获取两个集合的并集
     *
     * <p>
     * 返回一个新的 {@code Set}，包含 {@code c1} 和 {@code c2} 中所有不重复的元素，
     * 如果所有集合为 {@code null} 或空，返回空 {@code Set}
     *
     * @param c1 集合1
     * @param c2 集合2
     * @return 包含并集结果的新 {@code Set}
     */
    public static <T> Set<T> union(Collection<T> c1, Collection<T> c2) {
        Set<T> result = new HashSet<>();

        if (!isEmpty(c1)) {
            result.addAll(c1);
        }

        if (!isEmpty(c2)) {
            result.addAll(c2);
        }

        return result;
    }

    /**
     * 获取多个集合的并集
     *
     * <p>
     * 返回一个新的 {@code Set}，包含 {@code c1}、{@code c2} 以及 {@code more} 中所有不重复的元素，
     * 如果所有集合为 {@code null} 或空，返回空 {@code Set}
     *
     * @param c1   集合1
     * @param c2   集合2
     * @param more 更多集合
     * @return 包含并集结果的新 {@code Set}
     */
    @SafeVarargs
    public static <T> Set<T> union(Collection<T> c1, Collection<T> c2, Collection<T>... more) {
        Set<T> result = union(c1, c2);

        for (Collection<T> c : more) {
            result = union(result, c);
        }

        return result;
    }

    /**
     * 创建一个包含指定元素的新集合
     *
     * @param supplier 提供集合实例的构造器
     * @param elements 要包含的元素
     * @return 包含指定元素的新集合，或空集合(如果 {@code elements} 为 {@code null} 或空)
     */
    private static <T extends Collection<? super E>, E> T newCollection(Supplier<T> supplier, Iterator<E> elements) {
        T newCollection = checkSupplierAndGet(supplier);
        if (elements != null) {
            while (elements.hasNext()) {
                newCollection.add(elements.next());
            }
        }
        return newCollection;
    }

    /**
     * 将集合转为 {@code Set}
     *
     * @param collection 集合
     * @return 如果原集合是 Set，则返回原集合，否则返回一个新的 {@code HashSet}
     */
    private static <E> Set<E> toSetIfNeeded(Collection<E> collection) {
        Assert.notNull(collection, "Collection must not be null");
        return (collection instanceof Set) ? (Set<E>) collection : new HashSet<>(collection);
    }

    /**
     * 检查 {@code predicate}
     *
     * @param predicate Predicate
     */
    private static void checkPredicate(Predicate<?> predicate) {
        Assert.notNull(predicate, "Predicate must not be null");
    }

    /**
     * 检查 {@code supplier} 并获取
     *
     * @param supplier Supplier
     * @return {@code supplier} 提供的值
     */
    private static <T> T checkSupplierAndGet(Supplier<T> supplier) {
        Assert.notNull(supplier, "Supplier must not be null");
        T newCollection = supplier.get();
        Assert.notNull(newCollection, "Supplier value must not be null");
        return newCollection;
    }

}
